using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Threading;
//using Ricciolo.StylesExplorer.Forms;
using Ricciolo.StylesExplorer.MarkupReflection;
using System.Diagnostics;

namespace Ricciolo.StylesExplorer.Model
{
    class SingleAssemblyApplication : Component, IApplication
    {
        private readonly BamlAssembly asm;
        private IList<IAssembly> _assemblies;
        private AppDomainTypeResolver resolver;

        private string lastAssemblyDirectory;

        public SingleAssemblyApplication(string location)
        {
            // Segno l'ultima directory utilizzata
            lastAssemblyDirectory = Path.GetDirectoryName(location);

            resolver = AppDomainTypeResolver.GetIntoNewAppDomain(lastAssemblyDirectory);

            this.asm = resolver.LoadAssembly(location);
            this.Assemblies.Add(new DotNetAssembly(this, asm, resolver));

            BamlAssembly[] references = resolver.GetReferencedAssemblies(asm);
            
            // Carico le referenze
            foreach (BamlAssembly ba in references)
            {
                DotNetAssembly dotNetAssembly = new DotNetAssembly(this, ba, resolver);
                if (dotNetAssembly.XamlFiles.Count > 0)
                    this.Assemblies.Add(dotNetAssembly);
            }
        }

        #region IApplication Members

        /// <summary>
        /// Restituisce il nome dell'applicazione
        /// </summary>
        public string Name
        {
            get { return Path.GetFileNameWithoutExtension(this.Assemblies[0].Name); }
        }

        public event AssemblyResolveEventHandler AssemblyResolve
        {
            add { this.resolver.AssemblyResolve += value; }
            remove { this.resolver.AssemblyResolve -= value; }
        }

        /// <summary>
        /// Restituisce la lista degli assembly che contiene
        /// </summary>
        public IList<IAssembly> Assemblies
        {
            get
            {
                if (_assemblies == null)
                    _assemblies = new AssemblyCollection();
                return _assemblies;
            }
        }

        /// <summary>
        /// Aggiorna, eventualmente in asincrono, tutta l'applicazione che rappresenta
        /// </summary>
        /// <returns></returns>
        public IAsyncResult Refresh()
        {
            throw new NotImplementedException();
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing)
            {
                foreach (IAssembly asm in this.Assemblies)
                    if (asm is IDisposable)
                        ((IDisposable)asm).Dispose();
                this.Assemblies.Clear();

                if (resolver != null)
                    AppDomainTypeResolver.DestroyResolver(this.resolver);

                resolver = null;
            }
        }
    }
}
